//@skip-check method-too-many-params
//@skip-check constructor-function-return-section
//@skip-check doc-comment-export-function-return-section
//@skip-check doc-comment-parameter-section
#Область ПрограммныйИнтерфейс

//  Конструкторы

//  ЭлементыФормы[]
//
Функция СоздатьЭлементФормы(Схема, ИмяЭлемента) Экспорт
	НовыйЭлементФормы = Новый Структура;
	//  Измерения
	НовыйЭлементФормы.Вставить("Имя", ИмяЭлемента);
	//  Реквизиты
	НовыйЭлементФормы.Вставить("Параметр", Неопределено);
	НовыйЭлементФормы.Вставить("Таблица", Неопределено);
	НовыйЭлементФормы.Вставить("ПараметрТекущаяСтрока", Неопределено);
	НовыйЭлементФормы.Вставить("НаКлиенте", Истина);
	НовыйЭлементФормы.Вставить("ЭтоГруппа", Ложь);
	НовыйЭлементФормы.Вставить("ЭтоТаблица", Ложь);
	НовыйЭлементФормы.Вставить("ЭтоПолеВвода", Ложь);
	НовыйЭлементФормы.Вставить("ФункцияСостояния", Неопределено);
	НовыйЭлементФормы.Вставить("Порядок", 0);
	//  Связанные данные
	НовыйЭлементФормы.Вставить("Параметры", Новый Массив);//  ЭлементФормы -> ПараметрыЭлементов.Элемент
	НовыйЭлементФормы.Вставить("Свойства", Новый Массив);//  ЭлементФормы -> ПараметрыЭлементов.Элемент
	НовыйЭлементФормы.Вставить("Элементы", Новый Массив);//  ЭлементыФормы[]
	Схема.ЭлементыФормы[ИмяЭлемента] = НовыйЭлементФормы;
	Возврат НовыйЭлементФормы;
КонецФункции

//  ПараметрыЭлементов[]
//
Функция СоздатьПараметрЭлемента(Схема, Элемент, Параметр, Свойство = Неопределено, ПутьКДанным = "") Экспорт
	ИдентификаторПараметраЭлемента = ОбщийКлиентСервер.ИмяПоУникальномуИдентификатору();
	НовыйПараметрЭлемента = Новый Структура;
	НовыйПараметрЭлемента.Вставить("Идентификатор", ИдентификаторПараметраЭлемента);
	//  Измерения
	НовыйПараметрЭлемента.Вставить("Элемент", Элемент);
	НовыйПараметрЭлемента.Вставить("Параметр", Параметр);
	НовыйПараметрЭлемента.Вставить("Свойство", Свойство);
	//  Реквизиты
	НовыйПараметрЭлемента.Вставить("ПутьКДанным", ?(НЕ ЗначениеЗаполнено(ПутьКДанным), Параметр.Имя, ПутьКДанным));
	НовыйПараметрЭлемента.Вставить("ПараметрИспользование");
	//  Связанные Данные
	Схема.ПараметрыЭлементов[ИдентификаторПараметраЭлемента] = НовыйПараметрЭлемента;
	Если ЗначениеЗаполнено(Свойство) Тогда
		Элемент.Свойства.Добавить(ИдентификаторПараметраЭлемента);
	Иначе
		Элемент.Параметры.Добавить(ИдентификаторПараметраЭлемента);
	КонецЕсли;
	Параметр.ЗависимыеЭлементы.Добавить(ИдентификаторПараметраЭлемента);
	НовыйПараметрЭлемента.Вставить("Тип");
	Возврат НовыйПараметрЭлемента;
КонецФункции

//  Связи[]
//
Функция СоздатьСвязь(Схема, ПараметрСостояния, Параметр, ПутьКДанным = "", Значение = Неопределено, ПроверкаЗаполнения = Неопределено) Экспорт
	ИдентификаторСвязи = ОбщийКлиентСервер.ИмяПоУникальномуИдентификатору();
	НоваяЗависимость = Новый Структура;
	НоваяЗависимость.Вставить("Идентификатор", ИдентификаторСвязи);
	//  Измерения
	НоваяЗависимость.Вставить("ПараметрСостояния", ПараметрСостояния);
	НоваяЗависимость.Вставить("Параметр", Параметр);
	//  Реквизиты
	НоваяЗависимость.Вставить("ПутьКДанным", ПутьКДанным);
	НоваяЗависимость.Вставить("Значение", Значение);
	НоваяЗависимость.Вставить("ПараметрИспользование");
	НоваяЗависимость.Вставить("ПроверкаЗаполнения", ПроверкаЗаполнения);
	НоваяЗависимость.Вставить("Слабая", Ложь);
	//  Связанные Данные
	Схема.Связи[ИдентификаторСвязи] = НоваяЗависимость;
	ПараметрСостояния.ВходящиеСвязи.Добавить(ИдентификаторСвязи);
	Параметр.ИсходящиеСвязи.Добавить(ИдентификаторСвязи);
	Возврат НоваяЗависимость;
КонецФункции

//  Параметры[]
//
Функция СоздатьПараметр(Схема, ИмяПараметра, Вычисляемый = Ложь) Экспорт
	НовыйПараметрСостояния = Новый Структура;
	//  Измерения
	НовыйПараметрСостояния.Вставить("Имя", ИмяПараметра);
	НовыйПараметрСостояния.Вставить("ПутьКДанным", Неопределено);
	//  Реквизиты
	НовыйПараметрСостояния.Вставить("ЭтоТаблица", Ложь);
	НовыйПараметрСостояния.Вставить("Контекстный", Ложь);
	//  Реквизиты: Характеристики
	НовыйПараметрСостояния.Вставить("НаКлиенте", Ложь);
	НовыйПараметрСостояния.Вставить("ПроверкаЗаполнения", Истина);
	НовыйПараметрСостояния.Вставить("ПроверкаЗначения", Ложь);
	НовыйПараметрСостояния.Вставить("ЗаполнениеПоУмолчанию", Истина);
	//  Реквизиты: Таблица
	НовыйПараметрСостояния.Вставить("ПараметрТаблица", Неопределено);
	НовыйПараметрСостояния.Вставить("ПараметрОтборСтрок", Неопределено);
	НовыйПараметрСостояния.Вставить("ПараметрыКолонок", Неопределено);
	НовыйПараметрСостояния.Вставить("Ключ", Неопределено);
	//  Реквизиты: Параметризированные Характеристики	
	НовыйПараметрСостояния.Вставить("ПараметрИспользование", Неопределено);
	НовыйПараметрСостояния.Вставить("ПараметрПроверкаЗаполнения", Неопределено);
	НовыйПараметрСостояния.Вставить("ПараметрЗаполнениеПоУмолчанию", Неопределено);
	//  Вычисление И Порядок
	НовыйПараметрСостояния.Вставить("Выражение", Неопределено);
	НовыйПараметрСостояния.Вставить("ИндексЗначения", Неопределено);
	НовыйПараметрСостояния.Вставить("Порядок", Неопределено);
	НовыйПараметрСостояния.Вставить("Вычисляемый", Вычисляемый);//  значение параметра не сохраняется. Используется для параметров, которые не сериализуются, но могут быть вычислены по месту
	//  События
	НовыйПараметрСостояния.Вставить("ОбработчикПриИзменении", Неопределено);
	//  Связи
	НовыйПараметрСостояния.Вставить("ВходящиеСвязи", Новый Массив);//  ПараметрСостояния -> Связи.ПараметрСостояния
	НовыйПараметрСостояния.Вставить("ИсходящиеСвязи", Новый Массив);//  ПараметрСостояния -> Связи.Параметр
	НовыйПараметрСостояния.Вставить("ЗависимыеЭлементы", Новый Массив);//  ПараметрСостояния -> ПараметрыЭлементов.Параметр
	НовыйПараметрСостояния.Вставить("Элементы", Новый Массив);// элементы, которые ссылаются на параметр
	НовыйПараметрСостояния.Вставить("ЭлементыСвязей", Новый Массив);// элемент, которые зависят по связям
	//  Связанные Данные
	Схема.ПараметрыСостояния[ИмяПараметра] = НовыйПараметрСостояния;
	//
	НовыйПараметрСостояния.Вставить("Тип", Неопределено);
	Возврат НовыйПараметрСостояния;
КонецФункции

//  Функции получения

// Возвращает найденный или новый параметр состояния
// 
// Возвращаемое значение:
//  Структура -- параметр состояния, 
// См. СоздатьПараметр
Функция ПараметрСостояния(Схема, Путь = "", Имя = "", Контекстный = Неопределено, Тип = Неопределено, Вычисляемый = Ложь) Экспорт
	Перем ПараметрСостояния;
	ПутьКДанным = ?(ЗначениеЗаполнено(Путь), Путь, ОбщийКлиентСервер.ИмяПоУникальномуИдентификатору());
	ИмяПараметра = ОбщийКлиентСервер.ЕстьПустоеЗначение(Имя, ПутьКДанным);
	ПараметрСостояния = Схема.ПараметрыСостояния[ИмяПараметра];
	Если ПараметрСостояния <> Неопределено Тогда
		Если Контекстный <> Неопределено Тогда
			ПараметрСостояния.Контекстный = Контекстный;
		КонецЕсли;
		Если Тип <> Неопределено Тогда
			Если ТипЗнч(Тип) = Тип("Строка") Тогда
				ПараметрСостояния.Тип = Новый ОписаниеТипов(Тип);
			Иначе
				ПараметрСостояния.Тип = Новый ОписаниеТипов(ОбщегоНазначенияКлиентСервер.ЗначениеВМассиве(Тип));			 
			КонецЕсли;
			Если Тип = Новый ОписаниеТипов("Булево") Тогда
				ПараметрСостояния.ПроверкаЗаполнения = Ложь;
			КонецЕсли;
		КонецЕсли;
		Возврат ПараметрСостояния;
	КонецЕсли;
	ПараметрСостояния = СоздатьПараметр(Схема, ИмяПараметра, Вычисляемый);
	Схема.ПараметрыСостояния[ИмяПараметра] = ПараметрСостояния;
	//  Путь, Контекстный
	Если ЗначениеЗаполнено(ПутьКДанным) Тогда
		СоставПути = СтрРазделить(ПутьКДанным, ".");
		ПутьКДаннымБазовогоПараметра = СоставПути[0];
		Если ОбщегоНазначенияКлиентСервер.ЕстьРеквизитИлиСвойствоОбъекта(Схема.Объект, ПутьКДаннымБазовогоПараметра) Тогда
			ЭтоКонтекст = Ложь;
			ЭтоРеквизитИлиСвойство = Истина;
		ИначеЕсли ОбщегоНазначенияКлиентСервер.ЕстьРеквизитИлиСвойствоОбъекта(Схема.Контекст, ПутьКДаннымБазовогоПараметра) Тогда
			ЭтоКонтекст = Истина;
			ЭтоРеквизитИлиСвойство = Истина;
		Иначе
			ЭтоКонтекст = Истина;
			ЭтоРеквизитИлиСвойство = Ложь;
		КонецЕсли;
	Иначе
		ЭтоКонтекст = Истина;
		ЭтоРеквизитИлиСвойство = Ложь;
	КонецЕсли;
	ПараметрСостояния.Контекстный = ЭтоКонтекст;
	Если ЭтоРеквизитИлиСвойство Тогда
		ПараметрСостояния.ПутьКДанным = ПутьКДанным;
		Если СоставПути.Количество() = 1 Тогда
			Если ЭтоКонтекст Тогда
				Значение = Схема.Контекст[ПутьКДаннымБазовогоПараметра];
				ТипЗначения = ТипЗнч(Значение);
			Иначе
				Значение = Схема.Объект[ПутьКДаннымБазовогоПараметра];
				ТипЗначения = ТипЗнч(Значение);
			КонецЕсли;
			Если ТипЗначения = Тип("ТаблицаЗначений") ИЛИ ТипЗначения = Тип("ДеревоЗначений") Тогда
				ПараметрСостояния.ЭтоТаблица = Истина;
				ПараметрСостояния.ПараметрыКолонок = ПараметрыКолонок(Схема, ПараметрСостояния, Значение.Колонки);
			ИначеЕсли ТипЗначения = Тип("ДанныеФормыКоллекция") Тогда
				ПараметрСостояния.ЭтоТаблица = Истина;
				ПараметрСостояния.ПараметрыКолонок = ПараметрыКолонок(Схема, ПараметрСостояния, Значение.Выгрузить(Новый Массив).Колонки, "ИсходныйНомерСтроки, НомерСтроки");
			ИначеЕсли ТипЗначения = Тип("ДанныеФормыДерево") Тогда
				ПараметрСостояния.ЭтоТаблица = Истина;
				ПараметрСостояния.ПараметрыКолонок = ПараметрыКолонок(Схема, ПараметрСостояния, ДанныеФормыВЗначение(Значение, Тип("ДеревоЗначений")).Колонки);
			ИначеЕсли СтрНайти(ТипЗначения, "ТабличнаяЧасть.") > 0 Тогда
				ПараметрСостояния.ЭтоТаблица = Истина;
				ПараметрСостояния.ПараметрыКолонок = ПараметрыКолонок(Схема, ПараметрСостояния, Значение.Выгрузить(Новый Массив).Колонки, "НомерСтроки");
			КонецЕсли;
		Иначе
			БазовыйПараметр = ПараметрСостояния(Схема, ПутьКДаннымБазовогоПараметра);
			Если БазовыйПараметр.ЭтоТаблица Тогда
				ПараметрСостояния.ПараметрТаблица = БазовыйПараметр;			
			КонецЕсли;
		КонецЕсли;
	ИначеЕсли НЕ Вычисляемый Тогда
		Схема.ЗначенияПараметров.Добавить(Новый Структура("Параметр, Значение", ПараметрСостояния, Неопределено));
		ПараметрСостояния.ИндексЗначения = Схема.ЗначенияПараметров.Количество() - 1;
	КонецЕсли;
	Если Тип <> Неопределено Тогда
		Если ТипЗнч(Тип) = Тип("Строка") Тогда
			ПараметрСостояния.Тип = Новый ОписаниеТипов(Тип);
		Иначе
			ПараметрСостояния.Тип = Новый ОписаниеТипов(ОбщегоНазначенияКлиентСервер.ЗначениеВМассиве(Тип));			 
		КонецЕсли;
	КонецЕсли;
	Если Тип = Новый ОписаниеТипов("Булево") Тогда
		ПараметрСостояния.ПроверкаЗаполнения = Ложь;
	КонецЕсли;
	Возврат ПараметрСостояния;
КонецФункции

Функция ЭлементФормы(Схема, ЭлементИлиИмя = "ЭтаФорма") Экспорт
	//  Определить ИмяЭлемента (ИмяЭлемента|ЭтаФорма), Элемент (Элемент|ЭтаФорма)
	Если ТипЗнч(ЭлементИлиИмя) = Тип("Строка") Тогда
		ИмяЭлемента = ЭлементИлиИмя;
		Если ЭлементИлиИмя = "ЭтаФорма" Тогда
			Элемент = Схема.Контекст;
		Иначе
			Элемент = Схема.Контекст.Элементы.Найти(ИмяЭлемента);
		КонецЕсли;
	ИначеЕсли ТипЗнч(ЭлементИлиИмя) = Тип("ФормаКлиентскогоПриложения") Тогда
		ИмяЭлемента = "ЭтаФорма";
		Элемент = Схема.Контекст;
	Иначе
		ИмяЭлемента = ЭлементИлиИмя.Имя;
		Элемент = Схема.Контекст.Элементы.Найти(ИмяЭлемента);
	КонецЕсли;
	//  Создание элемента формы модели состояния
	ЭлементФормы = Схема.ЭлементыФормы[ИмяЭлемента];
	Если ЭлементФормы <> Неопределено Тогда
		Возврат ЭлементФормы;
	КонецЕсли;
	ЭлементФормы = СоздатьЭлементФормы(Схема, ИмяЭлемента);
	Если ИмяЭлемента = "ЭтаФорма" Тогда
		Возврат ЭлементФормы;
	КонецЕсли;
	//  Донастройка элемента формы модели состояния: ЭтоТаблица, ЭтоПолеВвода, Параметр
	ТипЭлемента = ТипЗнч(Элемент);
	ПутьКДанным = "";
	Если ТипЭлемента = Тип("ТаблицаФормы") Тогда
		ЭлементФормы.ЭтоТаблица = Истина;
		ПутьКДанным = Элемент.ПутьКДанным;
	ИначеЕсли ТипЭлемента = Тип("ПолеФормы") Тогда // И Элемент.Вид = ВидПоляФормы.ПолеВвода
		ЭлементФормы.ЭтоПолеВвода = Истина;
		ПутьКДанным = Элемент.ПутьКДанным;
	КонецЕсли;
	Если СтрНачинаетсяС(ПутьКДанным, "Элементы") Тогда
		//Элементы(0).ЭлементТаблицы(1).ТекущиеДанные(2).Реквизит(3) - так можно выводить поля формы, которые ссылаются на текущие данные в таблице
		Состав = СтрРазделить(ПутьКДанным, ".");
		ЭлементФормы.Таблица = Состав[1];
		ПутьКДанным = Схема.Контекст.Элементы[ЭлементФормы.Таблица].ПутьКДанным + "." + Состав[3];
	КонецЕсли;
	Если СтрНачинаетсяС(ПутьКДанным, Схема.ПутьКДаннымОбъекта) Тогда
		ПутьКДанным = Прав(ПутьКДанным, СтрДлина(ПутьКДанным) - СтрДлина(Схема.ПутьКДаннымОбъекта) - 1);
	КонецЕсли;
	//  Заполнение параметра элемента
	Если ЗначениеЗаполнено(ПутьКДанным) Тогда
		ПараметрЭлемента = ПараметрСостояния(Схема, ПутьКДанным);
		ПараметрЭлемента.Элементы.Добавить(ЭлементФормы.Имя);
		ЭлементФормы.Параметр = ПараметрЭлемента;
		//  Добавить зависимость по параметрам связей
		Если ЗначениеЗаполнено(ПараметрЭлемента.ПараметрИспользование) Тогда
			ОбщегоНазначенияКлиентСервер.ДополнитьМассив(ПараметрЭлемента.ПараметрИспользование.ЭлементыСвязей, ПараметрЭлемента.Элементы, Истина);
		КонецЕсли;
		Для Каждого ИдентификаторСвязи Из ПараметрЭлемента.ВходящиеСвязи Цикл
			Связь = Схема.Связи[ИдентификаторСвязи];
			Если ЗначениеЗаполнено(Связь.Параметр.ПараметрИспользование) Тогда
				ОбщегоНазначенияКлиентСервер.ДополнитьМассив(Связь.Параметр.ПараметрИспользование.ЭлементыСвязей, ПараметрЭлемента.Элементы, Истина);
			КонецЕсли;
			Если ЗначениеЗаполнено(Связь.ПараметрИспользование) Тогда
				ОбщегоНазначенияКлиентСервер.ДополнитьМассив(Связь.ПараметрИспользование.ЭлементыСвязей, ПараметрЭлемента.Элементы, Истина);
			КонецЕсли;
		КонецЦикла;
	КонецЕсли;
	Возврат ЭлементФормы;
КонецФункции

Функция Связь(Схема, ПараметрСостояния, Параметр, ПутьКДанным = "", Значение = Неопределено, ПроверкаЗаполнения = Неопределено) Экспорт
	Возврат СоздатьСвязь(Схема, ПараметрСостояния, Параметр, ?(НЕ ЗначениеЗаполнено(ПутьКДанным), Параметр.Имя, ПутьКДанным), Значение, ПроверкаЗаполнения);
КонецФункции

// НастройкаЭлементовФормы

Процедура УстановитьДействие(Элемент, ИмяСобытия, Действие) Экспорт
	Если НЕ ЗначениеЗаполнено(Элемент.ПолучитьДействие(ИмяСобытия)) Тогда
		Элемент.УстановитьДействие(ИмяСобытия, Действие);
	КонецЕсли;
КонецПроцедуры

Процедура ДобавитьЭлементыФормы(Схема) Экспорт
	УстановитьДействие(Схема.Контекст, "ПриОткрытии", "ПриОткрытииВМоделиФормы");
	Для Каждого Элемент Из Схема.Контекст.Элементы Цикл
		ТипЭлемента = ТипЗнч(Элемент);
		Если ТипЭлемента = Тип("ТаблицаФормы") ИЛИ ТипЭлемента = Тип("ПолеФормы") Тогда
			ЭлементФормы = ЭлементФормы(Схема, Элемент.Имя);
			Если ТипЭлемента = Тип("ТаблицаФормы") Тогда
				ЭлементФормы.ЭтоТаблица = Истина;
				УстановитьДействие(Элемент, "ПриАктивизацииСтроки", "ПриАктивизацииСтрокиТаблицыФормы");
				Для Каждого ПодчиненныйЭлемент Из РаботаСМодельюФормыКлиентСервер.НайтиПодчиненныеЭлементы(Элемент) Цикл
					ЭлементТаблицы = ЭлементФормы(Схема, ПодчиненныйЭлемент.Имя);
					ЭлементТаблицы.Таблица = Элемент.Имя;					
				КонецЦикла;
				УстановитьДействие(Элемент, "ПередНачаломДобавления", "ПередНачаломДобавленияСтрокиТаблицыФормы");
				УстановитьДействие(Элемент, "ПередНачаломИзменения", "ПередНачаломИзмененияСтрокиТаблицыФормы");
				УстановитьДействие(Элемент, "ПередОкончаниемРедактирования", "ПередОкончаниемРедактированияСтрокиТаблицыФормы");
				УстановитьДействие(Элемент, "ПередУдалением", "ПередУдалениемСтрокиТаблицыФормы");
				УстановитьДействие(Элемент, "ПриНачалеРедактирования", "ПриНачалеРедактированияСтрокиТаблицыФормы");
				УстановитьДействие(Элемент, "ПриОкончанииРедактирования", "ПриОкончанииРедактированияСтрокиТаблицыФормы");
				УстановитьДействие(Элемент, "Выбор", "ВыборСтрокиТаблицыФормы");
				Продолжить;
			ИначеЕсли ТипЭлемента = Тип("ПолеФормы") И Элемент.Вид = ВидПоляФормы.ПолеВвода Тогда
				УстановитьДействие(Элемент, "НачалоВыбора", "НачалоВыбора");
				ЭлементФормы.ЭтоПолеВвода = Истина;
			КонецЕсли;
			УстановитьДействие(Элемент, "ПриИзменении", "ПриИзменении");
		КонецЕсли;
	КонецЦикла;
КонецПроцедуры

//  Конструирование структуры схемы для построения модели объекта
//
Функция СхемаМодели(Контекст, ПутьКДаннымОбъекта = "Объект", МодульМодели = "") Экспорт
	Схема = Новый Структура;
	Если ТипЗнч(Контекст) = Тип("ФормаКлиентскогоПриложения") Тогда
		Если ЗначениеЗаполнено(ПутьКДаннымОбъекта) Тогда
			Схема.Вставить("Объект", ОбщегоНазначенияКлиентСервер.ПолучитьРеквизитФормыПоПути(Контекст, ПутьКДаннымОбъекта));
		Иначе
			Схема.Вставить("Объект", Контекст);
		КонецЕсли;
		Схема.Вставить("ЭлементыФормы", Новый Соответствие);
		Схема.Вставить("ПараметрыЭлементов", Новый Соответствие);
	Иначе
		Схема.Вставить("Объект", Контекст);
	КонецЕсли;
	Схема.Вставить("ПутьКДаннымОбъекта", ПутьКДаннымОбъекта);
	Схема.Вставить("ПараметрыСостояния", Новый Соответствие);
	Схема.Вставить("Связи", Новый Соответствие);
	Схема.Вставить("Контекст", Контекст);
	Схема.Вставить("Модуль", МодульМодели);
	Схема.Вставить("ОбработчикИнициализацииДанных", Неопределено);
	Схема.Вставить("ЗначенияПараметров", Новый Массив);
	Схема.Вставить("ЭтоКонтекстФормы", ТипЗнч(Контекст) = Тип("ФормаКлиентскогоПриложения"));
	Возврат Схема;
КонецФункции

//  Инстанцирование данных модели в объекте
//	
Процедура ПрименитьМодель(Схема) Экспорт
	МодельТаблицы = Общий.МодельТаблицы();
	МодельТаблицы.Таблица("ЗначенияПараметров")
		.Колонка("Параметр").ТипСтрока(255)
		.Колонка("Значение").ТипПроизвольный()
	;
	Контекст = Схема.Контекст;
	Если ТипЗнч(Контекст) = Тип("ФормаКлиентскогоПриложения") Тогда
		Если НЕ ОбщегоНазначенияКлиентСервер.ЕстьРеквизитИлиСвойствоОбъекта(Контекст, "ЗначенияПараметров") Тогда
			НовыеРеквизиты = Новый Массив;
			НовыеРеквизиты.Добавить(Новый РеквизитФормы("ПутьКДаннымОбъекта", ОбщегоНазначения.ОписаниеТипаСтрока(50)));
			НовыеРеквизиты.Добавить(Новый РеквизитФормы("МодульМодели", ОбщегоНазначения.ОписаниеТипаСтрока(150)));
			НовыеРеквизиты.Добавить(Новый РеквизитФормы("ПараметрыСостояния", Новый ОписаниеТипов));
			НовыеРеквизиты.Добавить(Новый РеквизитФормы("Связи", Новый ОписаниеТипов));
			НовыеРеквизиты.Добавить(Новый РеквизитФормы("ЭлементыФормы", Новый ОписаниеТипов));
			НовыеРеквизиты.Добавить(Новый РеквизитФормы("ПараметрыЭлементов", Новый ОписаниеТипов));
			МодельТаблицы.СоздатьТаблицыВРеквизитахФормы(НовыеРеквизиты);
			Контекст.ИзменитьРеквизиты(НовыеРеквизиты);
		КонецЕсли;
		//  Контекст Модели
		Контекст.ПутьКДаннымОбъекта = Схема.ПутьКДаннымОбъекта;
		Контекст.МодульМодели = Схема.Модуль;
		//  Контекст Объекта
		Контекст.ПараметрыСостояния = Новый ФиксированноеСоответствие(Схема.ПараметрыСостояния);
		Контекст.Связи = Новый ФиксированноеСоответствие(Схема.Связи);
		//  Контекст Формы
		Контекст.ЭлементыФормы = Новый ФиксированноеСоответствие(Схема.ЭлементыФормы);
		Контекст.ПараметрыЭлементов = Новый ФиксированноеСоответствие(Схема.ПараметрыЭлементов);
		//
		Контекст.ЗначенияПараметров.Очистить();
		Для Каждого ЭлементЗначенияПараметра Из Схема.ЗначенияПараметров Цикл
			ЗначениеПараметра = Контекст.ЗначенияПараметров.Добавить();
			ЗначениеПараметра.Значение = ЭлементЗначенияПараметра.Значение;
			ЗначениеПараметра.Параметр = ЭлементЗначенияПараметра.Параметр.Имя;
		КонецЦикла;
	Иначе
		ДополнительныеСвойства = Контекст.ДополнительныеСвойства;
		МодельТаблицы.СоздатьТаблицыВСтруктуре(ДополнительныеСвойства);
		//  Контекст Модели
		ДополнительныеСвойства.Вставить("ПутьКДаннымОбъекта", Схема.ПутьКДаннымОбъекта);
		ДополнительныеСвойства.Вставить("МодульМодели", Схема.Модуль);
		//  Контекст Объекта
		ДополнительныеСвойства.Вставить("ПараметрыСостояния", Схема.ПараметрыСостояния);
		ДополнительныеСвойства.Вставить("Связи", Схема.Связи);
		//
		Для Каждого ЭлементЗначенияПараметра Из Схема.ЗначенияПараметров Цикл
			ЗначениеПараметра = ДополнительныеСвойства.ЗначенияПараметров.Добавить();
			ЗначениеПараметра.Значение = ЭлементЗначенияПараметра.Значение;
			ЗначениеПараметра.Параметр = ЭлементЗначенияПараметра.Параметр.Имя;
		КонецЦикла;
	КонецЕсли;
КонецПроцедуры

Процедура ОпределитьПорядок(Схема) Экспорт
	Перем ПараметрСостояния;
	Порядок = 0;
	Для Каждого КлючЗначение Из Схема.ПараметрыСостояния Цикл
		ПараметрСостояния = КлючЗначение.Значение;
		Если ЗначениеЗаполнено(ПараметрСостояния.Порядок) Тогда
			Порядок = Макс(Порядок, ПараметрСостояния.Порядок);
			Продолжить;
		КонецЕсли;
		Порядок = ПорядокПараметра(Схема, ПараметрСостояния, Порядок) + 1;
		ПараметрСостояния.Порядок = Порядок;
	КонецЦикла;
КонецПроцедуры

Процедура ПрименитьМодельОбъекта(Схема) Экспорт
	ПрименитьМодель(Схема);
КонецПроцедуры

//  Работа с моделью через DSL
//
Функция МодельСостояния(Контекст, ПутьКДаннымОбъекта = "Объект", МодульМодели = "Контекст") Экспорт
	Возврат Обработки.МодельСостояния
		.Создать()
		.УстановитьСхему(Контекст, ПутьКДаннымОбъекта, МодульМодели)
	;
КонецФункции

#КонецОбласти

#Область СлужебныеПроцедурыИФункции

Функция ПараметрыКолонок(Схема, ПараметрТаблицы, Колонки, ИсключитьКолонки = "")
	ОписанияКолонок = Новый Структура;
	КолонкиИсключения = ОбщийКлиентСервер.Массив(ИсключитьКолонки);
	Для Каждого Колонка Из Колонки Цикл
		Если КолонкиИсключения.Найти(Колонка.Имя) <> Неопределено Тогда
			Продолжить;
		КонецЕсли;
		ПутьКДанным = ПараметрТаблицы.ПутьКДанным + "." + Колонка.Имя;				
		ПараметрСостояния(Схема, ПутьКДанным);
		ОписанияКолонок.Вставить(Колонка.Имя, ПутьКДанным);		
	КонецЦикла;
	Возврат ОписанияКолонок;
КонецФункции	

Функция ПорядокПараметра(Схема, Параметр, Знач Порядок)
	Перем ПараметрСостояния;
	Перем Связь;
	Для Каждого Связь Из Параметр.ИсходящиеСвязи Цикл
		ПараметрСостояния = Схема.Связи[Связь].ПараметрСостояния;		
		Если ЗначениеЗаполнено(ПараметрСостояния.Порядок) Тогда
			Порядок = Макс(Порядок, ПараметрСостояния.Порядок);
			Продолжить;
		КонецЕсли;
		Порядок = ПорядокПараметра(Схема, ПараметрСостояния, Порядок) + 1;
		ПараметрСостояния.Порядок = Порядок;
	КонецЦикла;
	Возврат Порядок;
КонецФункции

#КонецОбласти
